#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@author: LiangChao
@email：kevinleong1011@hotmail.com
@desc: 
"""
import inspect
import os

from makit import py, Path
from makit.py import PyModule

from .errors import InvalidTestError, InvalidPluginError
from .plugin import PluginCaller, Plugin


def parse_project_package(target):
    if inspect.ismodule(target):
        module_name = target.__name__
        if module_name == '__main__':
            root_path = parse_project_root(target.__file__)
            root_package = root_path.basename
        else:
            root_package = module_name.split('.')[0]
    elif isinstance(target, str):
        if os.path.exists(target):
            project_path = parse_project_root(target)
            root_package = project_path.basename
            py.insert(project_path.parent)
        else:
            root_package = target
    else:
        raise InvalidTestError(target)
    return root_package


def parse_project_root(path):
    path = os.path.abspath(path)
    path = Path(path)
    root = path.parent if os.path.isfile(str(path)) else path
    if not (root / '__init__.py').exists:
        for _, path, _ in root.walk('__init__.py'):
            return path.parent, path.parent.basename
    else:
        while (root / '__init__.py').exists:
            path = root
            root = root.parent
    return path


class Project:
    """
    工程项目
    """

    def __init__(self, module, root=None):
        self._root_path = root or os.path.dirname(module.__file__)
        self._name = module.__name__
        self.module = module
        self.scripts = []
        self.plugin = PluginCaller()
        self.config = getattr(module, 'config', None)  # Settings({})  # 项目配置
        self.tasks = []
        self.filters = []  # 测试过滤器

    @property
    def name(self):
        """
        Project name
        """
        return self._name

    @property
    def root_path(self):
        if self._root_path is None:
            module = PyModule(self.module)
            self._root_path = parse_project_root(module.filename)
        return self._root_path

    # def load_config(self):
    #     # 配置支持：config.py、conf.py、settings.yml、settings.ini
    #     cfg_file = os.path.join(self.root_path, 'config.py')
    #     if os.path.exists(cfg_file):
    #         module = py.get_object(cfg_file)
    #         self.config.inherit(config).load_module(module)
    #         self._load_plugins()

    def _load_plugins(self):
        plugins = self.config.PLUGINS.data
        for plugin in plugins:
            if isinstance(plugin, str):
                plugin = py.get_object(plugin)
            if isinstance(plugin, type):
                plugin = plugin(self)
            elif inspect.ismodule(plugin):
                plugin = Plugin(plugin)
            else:
                raise InvalidPluginError(plugin)
            self.plugin.add_plugin(plugin)

    def filter_py(self, script, context):
        if self.filters and not all(map(lambda f: f(script), self.filters)):
            return False
        results = self.plugin.filter_script(script, context)
        return not results or all(results)

    def filter_test(self, method_node, context):
        marks = context.data.marks
        if marks and not method_node.has_marks(*marks):
            return False
        if self.filters and not all(map(lambda f: f(method_node), self.filters)):
            return False
        results = self.plugin.filter_test(method_node, context)
        return not results or all(results)

    def __repr__(self):
        return f'<TestProject {self.name}>'
